/* 
 * Copyright 2010 HIT-CIR (HIT Center for Information Retrieval). 
 * 
 * author: chuter
 * mail:   lliu@ir.hit.edu.cn, topgun.chuter@gmail.com
 */
package edu.hit.irlab.coref.resolve;

import java.util.ArrayList;
import java.util.HashMap;

import edu.hit.irlab.coref.mentionfinder.Mention;

/**
 * Just cluster the <code>Mentions</code> that are <code>Coreference</code>
 * ,which was annotated in the specific <code>Corpus</code>
 *
 * @author chuter
 *
 */
public abstract class AbstractCorpusResolver implements Resolver {
		
	protected abstract ArrayList<Entity> entityFilter(
			ArrayList<Entity> entity_lis);
	
	/**
	 * Clustering the <code>Mentions</code> into sets
	 * as <code>Entity List</code> in fact<br>
	 * The <code>Mentions</code> must contain the <code>index</code>
	 * of the <code>Mention</code> they refer to, then
	 * you can get a Mention's Ancestor Mention by mentions[<code>index</code>]
	 * 
	 * @see edu.hit.irlab.coref.mentionfinder.Mention#getRefMention_index()
	 */
	public ArrayList<Entity> resolve(Mention[] mentions) {		
		ArrayList<Entity> entity_lis = new ArrayList<Entity>();
		HashMap<Integer, Integer> men_ent_idMap = new HashMap<Integer, Integer>();
		int entId = 0;
//		HashSet<Integer> delSet = new HashSet<Integer>();
		for (Mention m : mentions) {
			int menId = m.mention_index;
			int refMenId = m.getRefMention_index();
			assert (menId>=0 && menId < mentions.length && refMenId < mentions.length);
//			if (delSet.contains(menId) || delSet.contains(refMenId)) 
//				continue;
//			if (refMenId > menId) {
//				delSet.add(refMenId);
//				delSet.add(menId);
//				continue;
//			}
			if (men_ent_idMap.containsKey(refMenId)) {
				if (men_ent_idMap.containsKey(menId))
					continue;
				int entityId = men_ent_idMap.get(refMenId);
				entity_lis.get(entityId).addmention(m);
				men_ent_idMap.put(menId, entityId);
				m.setSetId(entityId);
			} else {
				Entity new_entity = null;
				if (refMenId<0) {
					if (!men_ent_idMap.containsKey(menId)) {
						new_entity = new Entity(
								String.valueOf(entId),
								new Mention[]{m}
							);
					}
				} else {
					new_entity = new Entity(
							String.valueOf(entId),
							new Mention[]{m, mentions[refMenId]}
						);
					men_ent_idMap.put(refMenId, entId);
					mentions[refMenId].setSetId(entId);
				}
				if (new_entity != null) {
					entity_lis.add(new_entity);
					m.setSetId(entId);
					men_ent_idMap.put(menId, entId++);
				}
			}
		}
		
		return entityFilter(entity_lis);
	}
	
	
}
